﻿#ifndef __UI_OBJECT_H__
#define __UI_OBJECT_H__

#include "base/object.h"
#include "graphics/graphics.h"
#include "container/inputhelper.h"

namespace MiniUI
{

class Graphics;
class UIObject;
class View;
class WinView;

typedef void (Delegater::*OnClickEventFunc)(const UIObject* sender, const Type::MiniPoint& pt, MouseButton button, uint keyState);
typedef void (Delegater::*OnMouseEventFunc)(const UIObject* sender, const Type::MiniPoint& pt, MouseButton button, uint keyState);
typedef void (Delegater::*OnMouseMoveEventFunc)(const UIObject* sender, const Type::MiniPoint& pt, uint keyState);
typedef void (Delegater::*OnMouseWheelEventFunc)(const UIObject* sender, const Type::MiniPoint& pt, uint keyState, int16 zDelta);
typedef void (Delegater::*OnChangeEventFunc)(const UIObject* sender, const Type::MiniRect& rect);
typedef void (Delegater::*OnMoveEventFunc)(const UIObject* sender, const Type::MiniPoint& ptSrc, const Type::MiniPoint& ptDst);
typedef void (Delegater::*OnResizeEventFunc)(const UIObject* sender, const Type::MiniSize& szOld, const Type::MiniSize& szNew);
typedef void (Delegater::*OnFocusEventFunc)(const UIObject* sender, bool bFocus);

class UIObject : public Object
{
    friend class View;
public:
    enum ANCHORS
    {
        ANCHOR_LEFT = 0x01,
        ANCHOR_TOP = 0x02,
        ANCHOR_RIGHT = 0x04,
        ANCHOR_BOTTOM = 0x08
    };
    enum SHAPE
    {
        SHAPE_RECT,
        SHAPE_ROUNDRECT,
        SHAPE_CIRCLE,
        SHAPE_ARC
    };
public:
    UIObject(const char* szType);
    virtual ~UIObject();
public:
    virtual void SetWinView(WinView* pWinView);
    UIObject* GetNext() const;
    UIObject* GetPrev() const;
    View* GetParent() const;
    WinView* GetWinView() const;
public:
    void GetPos(Type::MiniPoint& pt) const;
    void SetPos(const Type::MiniPoint& pt, bool bUpdateMargin = true);
    void GetSize(Type::MiniSize& size) const;
    void SetSize(const Type::MiniSize& size, bool bUpdateMargin = true);
    void GetRect(Type::MiniRect& rect) const;
    void SetRect(const Type::MiniRect& rect, bool bUpdateMargin = true);
    void GetMargin(Type::MiniRect& rcMargin) const;
    void SetMargin(const Type::MiniRect& rcMargin);
    void UpdateRect(View* pParent);
    void UpdateMargin(View* pParent);
    void GetClientRect(Type::MiniRect& rect) const;
    void GetClientCursorPos(Type::MiniPoint& pt) const;
    void ClientToScreen(Type::MiniPoint& pt) const;
    void ScreenToClient(Type::MiniPoint& pt) const;
public:
    void SetBlendValue(uint8 value);
    uint8 GetBlendValue();
    void SetVisible(bool bVisible);
    bool GetVisible();
    void SetEnable(bool bEnable);
    bool GetEnable();
    void SetSelected(bool bSelected);
    bool GetSelected();
    void SetTransparent(bool bTransparent);
    bool GetTransparent();
    void SetCursor(CursorType cursor, void* customCursor = nullptr);
    CursorType GetCursor();
    void SetBackgroundColor(const Type::MiniARGB& color);
    void GetBackgroundColor(Type::MiniARGB& color);
    void SetShape(SHAPE shape);
    SHAPE GetShape();
    void SetAnchors(uint8 anchors);
    uint8 GetAnchors();
    bool CheckEnable();
    bool CheckVisible();
    bool SetFocus(bool bFocus);
    bool IsFocused();
public:
    virtual bool RenderTo(Graphics& graphics, const Type::MiniRect& rcRender, const uint8 blendValue) = 0;
    virtual bool HitTest(const Type::MiniPoint& pt);
    virtual void Update();
public:
    void DoClick(const Type::MiniPoint& pt, MouseButton button, uint keyState, bool& bHandled);
    void DoDblClk(const Type::MiniPoint& pt, MouseButton button, uint keyState, bool& bHandled);
    void DoMouseDown(const Type::MiniPoint& pt, MouseButton button, uint keyState, bool& bHandled);
    void DoMouseUp(const Type::MiniPoint& pt, MouseButton button, uint keyState, bool& bHandled);
    void DoMouseMove(const Type::MiniPoint& pt, uint keyState, bool& bHandled);
    void DoMouseHover();
    void DoMouseEnter();
    void DoMouseLeave();
    void DoMouseWheel(const Type::MiniPoint& pt, uint keyState, int16 zDelta, bool& bHandled);
    void DoChange(const Type::MiniRect& rect);
    void DoVisibleChange();
	void DoFocusChange(bool bFocus);
    void DoClose();
protected:
    void DoMove(const Type::MiniPoint& ptSrc, const Type::MiniPoint& ptDst);
    void DoResize(const Type::MiniSize& szOld, const Type::MiniSize& szNew);
    void DoParentChange();
protected:
    virtual bool Click(const Type::MiniPoint& pt, MouseButton button, uint keyState, bool& bHandled);
    virtual bool DblClk(const Type::MiniPoint& pt, MouseButton button, uint keyState, bool& bHandled);
    virtual bool MouseDown(const Type::MiniPoint& pt, MouseButton button, uint keyState, bool& bHandled);
    virtual bool MouseUp(const Type::MiniPoint& pt, MouseButton button, uint keyState, bool& bHandled);
    virtual bool MouseMove(const Type::MiniPoint& pt, uint keyState, bool& bHandled);
    virtual void MouseHover();
    virtual void MouseEnter();
    virtual void MouseLeave();
    virtual bool MouseWheel(const Type::MiniPoint& pt, uint keyState, int16 zDelta, bool& bHandled);
    virtual void Change(const Type::MiniRect& rect);
    virtual void Move(const Type::MiniPoint& ptSrc, const Type::MiniPoint& ptDst);
    virtual void Resize(const Type::MiniSize& szOld, const Type::MiniSize& szNew);
    virtual void VisibleChange(bool bVisible);
    virtual void FocusChange(bool bFocus);
protected:
    //clip graphics while render, the derived class should call it.
    void ShapeClip(Graphics& graphics);
protected:
    void NotifyParentChange(const Type::MiniRect& rect);
    void NotifyParentMove(const Type::MiniPoint& ptSrc, const Type::MiniPoint& ptDst);
    void NotifyParentResize(const Type::MiniSize& szOld, const Type::MiniSize& szNew);
public:
    Event<OnClickEventFunc> OnClick;
    Event<OnClickEventFunc> OnDblClick;
    Event<OnMouseEventFunc> OnMouseDown;
    Event<OnMouseEventFunc> OnMouseUp;
    Event<OnMouseMoveEventFunc> OnMouseMove;
    Event<OnNotifyEventFunc> OnMouseHover;
    Event<OnNotifyEventFunc> OnMouseEnter;
    Event<OnNotifyEventFunc> OnMouseLeave;
    Event<OnMouseWheelEventFunc> OnMouseWheel;
    Event<OnChangeEventFunc> OnChange;
    Event<OnMoveEventFunc> OnMove;
    Event<OnResizeEventFunc> OnResize;
    Event<OnFocusEventFunc> OnFocus;
    Event<OnNotifyEventFunc> OnVisibleChange;
    //Event<OnNotifyEventFunc> OnEnableChange;
protected:
    Type::MiniPoint m_pos;
    Type::MiniSize m_size;
    Type::MiniRect m_margin;
    Type::MiniARGB m_bgColor;
    SHAPE m_shape;
    uint8 m_blendValue;
    uint8 m_anchors;
    bool m_bVisible;
    bool m_bEnable;
    bool m_bSelected;
    bool m_bTransparent;
    CursorType m_cursor;
    void* m_customCursor;
protected:
    UIObject* m_pNext;
    UIObject* m_pPrev;
    WinView* m_pWinView;
    View* m_pParent;
};

}

#endif